package model;

import java.util.ArrayList;
import java.util.List;

import manager.IAnalizadorSintactico;
import manager.INodeData;
import manager.IToken;
import manager.ITokenStream;
import utils.TreeNode;
import visitors.BuildSymbolTableVisitor;
import visitors.LoggingVisitor;
import visitors.TreeVisitor;

public class G1 extends AbstractAnalizadorSintactico implements IAnalizadorSintactico {
	
	private List<TreeNode<INodeData>> listaMetodos = new ArrayList<TreeNode<INodeData>>();
	
	/* INICIALIZACION */	
	public G1 ( ITokenStream ts ) {
		super(ts, false);
	}
	public G1 ( ITokenStream ts, boolean debugMode ) {
		super(ts,debugMode);
	}
	
	/** 
	 *Devuelve true si reconoce un bloque de procedimientos y funciones o el fin de archivo
	 */
	public boolean reconocer () {
		
		boolean recognized = true; 
		
		this.setNroProduccion(PROD_ENCABEZADO);
		this.accept(LoggingVisitor.getInstance());	//Loguea encabezado

		/* <G'> ->	BLOQUE EOF |
					EOF 
		 */

		if ( this.getTokenSiguiente().equals( new Token(IToken.PALABRA_RESERVADA_PROCEDURE) ) ||  
				this.getTokenSiguiente().equals( new Token(IToken.PALABRA_RESERVADA_FUNCTION) )) {

			// <G'> -> BLOQUE EOF |
					
			// Reconocer <BLOQUE>
			while ( Bloque.primeros( this.getTokenSiguiente() ) ) {
				
				this.setNroProduccion(PROD_PRIMERA);
				this.accept(LoggingVisitor.getInstance());	//Loguea produccion actual

				IAnalizadorSintactico bloque = new Bloque(this.tokenStream, this.debugMode);
				recognized &= bloque.reconocer();
			}
		}

		this.setNroProduccion(PROD_SEGUNDA);

		//En este punto deberia encontrar TOKEN_FIN_DE_ARCHIVO
		recognized &= this.reconocerToken(IToken.TYPE_FIN_DE_ARCHIVO);
		
		this.accept(BuildSymbolTableVisitor.getInstance());	
		this.accept(TreeVisitor.getInstance());		
		
		return recognized;
	}
	
	public static boolean primeros(IToken token) {
		return  token.equals( new Token(IToken.PALABRA_RESERVADA_PROCEDURE) ) ||
				token.equals( new Token(IToken.PALABRA_RESERVADA_FUNCTION) );
	}
	
	public List<TreeNode<INodeData>> getListaMetodos() {
		return listaMetodos;
	}
}
